package com.thinkit.bigdata.core.util;

import com.thinkit.bigdata.core.entity.FtpPro;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;
import org.apache.tools.zip.ZipOutputStream;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.SocketException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 *
 * Created by BanAiQin on 2016/11/15.
 */

public class FileUtil {

    /**
     * 默认文件编码
     */
    private static String FILE_ENCODING = "UTF-8";

    private static Logger logger = Logger.getLogger(FileUtil.class.getName());

    /**
     * 创建文件
     * author：baq
     *
     * @param file
     */
    public static boolean createFile(File file) {
        boolean res = false;
        File p = file.getParentFile();
        if (!p.exists()) {
            p.mkdirs();//如果父目录不存在，则创建目录
        }
        if (!file.exists()) {
            try {
                res = file.createNewFile();//创建文件
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return res;
    }

    /**
     * 如果目录不存在，则创建目录
     * author：baq
     *
     * @param path -
     */
    public static boolean createDirectory(String path) {
        if (StringUtil.isEmpty(path)) {
            return false;
        }
        path = path.substring(0, path.lastIndexOf(StringUtil.FILESEPARATOR) + 1);
        if (!path.endsWith(StringUtil.FILESEPARATOR) && !path.endsWith("\\")) {
            path += StringUtil.FILESEPARATOR;
        }
        File file = new File(path);
        if (!file.exists()) {
            return file.mkdirs();
        }
        return true;
    }

    /**
     * 删除文件
     *
     * @param file -
     */
    public static boolean deleteFile(File file) {
        if (file.isFile() && file.exists()) {
            boolean del = file.delete();
            logger.info("【删除文件】文件路径：" + file.getAbsolutePath() + "【" + del + "】");
            return del;
        }
        return false;
    }

    /**
     * 判断文件是否存在
     *
     * @param dirFile -
     */
    public static boolean existsFile(File dirFile) {
        //如果dir对应的文件不存在，或者不是一个目录，则退出
        return dirFile.exists();
    }



    /**
     * 删除目录（文件夹）以及目录下的文件
     * author：baq
     *
     * @param sPath 被删除目录的文件路径
     * @return 目录删除成功返回true，否则返回false
     */
    public static boolean deleteDirectory(String sPath) {
        //如果sPath不以文件分隔符结尾，自动添加文件分隔符
        if (!sPath.endsWith(StringUtil.FILESEPARATOR)) {
            sPath = sPath + StringUtil.FILESEPARATOR;
        }
        File dirFile = new File(sPath);
        //如果dir对应的文件不存在，或者不是一个目录，则退出
        if (!dirFile.exists() || !dirFile.isDirectory()) {
            return false;
        }
        boolean flag = true;
        //删除文件夹下的所有文件(包括子目录)
        File[] files = dirFile.listFiles();
        for (File file : files) {
            //删除子文件
            if (file.isFile()) {
                flag = deleteFile(file);
                if (!flag) break;
            } //删除子目录
            else {
                flag = deleteDirectory(file.getAbsolutePath());
                if (!flag) break;
            }
        }
        if (!flag) return false;
        //删除当前目录
        return dirFile.delete();
    }

    public static boolean deleteUrlFile(List<String> fileUrls, String rootPath) {
        if (fileUrls != null && fileUrls.size() > 0) {
            rootPath = rootPath == null ? "" : rootPath;
            for (String fileUrl : fileUrls) {
                File file = new File(fileUrl);
                if (file.exists() && file.isFile()) {
                    boolean del = file.delete();
                    logger.info(del);
                } else {
                    file = new File(rootPath + fileUrl);
                    if (file.exists() && file.isFile()) {
                        file.delete();
                    }
                }
            }
        }
        return true;
    }

    // 删除FTP上的文件通用方法
    public static boolean deleteFileFtp(FtpPro ftp, String path, String fileName) {
        boolean del = false;
        try {
            FTPClient ftpClient = new FTPClient();
            //连接ftp
            ftpClient.connect(ftp.getHost(), ftp.getPort());
            ftpClient.login(ftp.getUsername(), ftp.getPassword());
            if (StringUtil.isNotEmpty(path)) {
                boolean pathRes = ftpClient.changeWorkingDirectory(path);
            }
            del = ftpClient.deleteFile(fileName);
            ftpClient.logout();
        } catch (Exception e) {
            logger.info("删除文件失败！请检查系统FTP设置,并确认FTP服务启动");
            return false;
        }
        return del;
    }

    /**
     * 下载文件
     *
     * @param file
     * @param response
     */
    public static void downloadFile(File file, HttpServletResponse response) {

        if (file == null) {
            return;
        }

        // 清空response
        response.reset();
        /**
         try{
         // 设置response的Header
         response.addHeader("Content-Disposition", "attachment;filename="+new String(file.getName().getBytes("utf8"),"iso-8859-1"));  //转码之后下载的文件不会出现中文乱码
         response.addHeader("Content-Length", "" + file.length());

         InputStream fis = new BufferedInputStream(new FileInputStream(file.getPath()));
         byte[] buffer = new byte[fis.available()];
         fis.read(buffer);


         OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
         toClient.write(buffer);
         toClient.flush();
         fis.close();
         toClient.close();
         }catch(Exception e){
         e.printStackTrace();
         }
         **/
        try {
            response.setContentType("text/html;charset=UTF-8");
            BufferedInputStream bis = null;
            BufferedOutputStream bos = null;

            response.addHeader("Content-Disposition", "attachment;filename=" + new String(file.getName().getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));  //转码之后下载的文件不会出现中文乱码
            response.addHeader("Content-Length", "" + file.length());

            bis = new BufferedInputStream(new FileInputStream(file.getPath()));
            bos = new BufferedOutputStream(response.getOutputStream());
            byte[] buff = new byte[2048];
            int bytesRead;
            while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
                bos.write(buff, 0, bytesRead);
            }
            bis.close();
            bos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 下载远程资源库中的文件至浏览器
     * author：baq
     *
     * @param fileUrl:远程文件的url
     * @param fileName：下载至浏览器的文件名
     * @param response -
     */
    public static void downloadFileFromUrl(String fileUrl, String fileName
            , HttpServletResponse response) throws IOException {

        if (StringUtil.isEmpty(fileUrl) || StringUtil.isEmpty(fileName)) {
            return;
        }
        InputStream stream = null;
        HttpURLConnection connection = null;
        response.reset();//清除下载文件的空白行
        OutputStream os = response.getOutputStream();//获取response输出流
        try {
            URL url = new URL(fileUrl);
            int downloaded = 0;
            connection = (HttpURLConnection) url.openConnection();//初始化到url的连接
            // Specify what portion of file to download.
            connection.setRequestProperty("Range", "bytes=" + downloaded + "-");
            connection.connect();//开始到url的server的连接
            int code = connection.getResponseCode();//连接返回值为200，表示连接成功
            if (code != 200 && code != 206) {
                os.write((" '" + fileUrl + "' 获取失败").getBytes());
                return;
            }
            int contentLength = connection.getContentLength();//确认下载内容不为空
            if (contentLength < 1) {
                os.write((" '" + fileUrl + "' 内容为空").getBytes());
                return;
            }

            int MAX_BUFFER_SIZE = 1024;//每次读取1024个字节，即1KB

            stream = connection.getInputStream();//获取 connection 输入流
            //当Content-Type 的类型为要下载的类型时 , Content-Disposition这个信息头会告诉浏览器这个文件的名字和类型。
            response.addHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));  //转码之后下载的文件不会出现中文乱码
            response.setContentType("application/octet-stream;charset=UTF-8");//把响应设置为二进制流
            do {
                byte buffer[];//根据文件大小确定每次读取的字节数
                if (contentLength - downloaded > MAX_BUFFER_SIZE) {
                    buffer = new byte[MAX_BUFFER_SIZE];
                } else {
                    buffer = new byte[contentLength - downloaded];
                }

                int read = stream.read(buffer);//从服务器中读取数据到buffer.
                if (read == -1)
                    break;
                os.write(buffer, 0, read);
                downloaded += read;
            } while (downloaded < contentLength);

        } catch (Exception e) {
            e.printStackTrace();
            os.write(("下载 '" + fileUrl + "' 遇到异常").getBytes());
        } finally {
            // 关闭输出流
            if (os != null) {
                try {
                    os.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            // 关闭到url的连接和输入流
            if (stream != null) {
                try {
                    stream.close();
                    connection.disconnect();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static boolean httpDownload(String httpUrl, String saveFile) {

        // 下载网络文件
        URL url = null;
        try {
            url = new URL(httpUrl);
        } catch (MalformedURLException e1) {
            e1.printStackTrace();
            return false;
        }
        HttpURLConnection conn = null;
        InputStream inStream = null;
        FileOutputStream fs = null;
        try {
            File file = new File(saveFile);
            File pFile = file.getParentFile();
            if (!pFile.exists()) {
                pFile.mkdirs();
            }

            file.createNewFile();

            conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(10 * 1000);
            conn.setReadTimeout(20 * 1000);

            if (conn.getResponseCode() == 200) {
                try {
                    inStream = conn.getInputStream();
                } catch (IOException e) {
                    logger.info("输入流错误");
                    return false;
                }
                try {
                    fs = new FileOutputStream(saveFile);
                } catch (FileNotFoundException e) {
                    logger.info("输出流错误");
                    return false;
                }

                byte[] buffer = new byte[2048];
                int len;
                try {
                    while ((len = inStream.read(buffer, 0, 2048)) != -1) {
                        fs.write(buffer, 0, len);
                    }
                } catch (IOException e) {
                    logger.info("读写错误");
                    return false;
                }
                return true;
            }
        } catch (FileNotFoundException e) {
            logger.info("下载视频创建文件异常");
            return false;
        } catch (IOException e) {
            logger.info("下载视频异常");
            return false;
        } finally {
            try {
                if (fs != null) {
                    fs.flush();
                    fs.close();
                    logger.info("关闭输入流");
                }
                if (inStream != null) {
                    inStream.close();
                    logger.info("关闭输出流");
                }
            } catch (IOException e) {
                logger.info("下载线程关闭流异常");
                return false;
            }
        }
        return false;
    }


    /**
     * 解压zip文件multipartfile到descDir文件下
     * 返回所有的语音文件列表
     *
     * @param multipartfile
     * @param descDir
     * @return
     */
    public static List<String> unZipFile(MultipartFile multipartfile, String descDir) {
        List<String> fileNameList = new ArrayList<String>();
        File pathFile = new File(descDir);
        if (!pathFile.exists()) {
            pathFile.mkdirs();
        }
        String zipName = multipartfile.getOriginalFilename();
        File file = new File(descDir + StringUtil.FILESEPARATOR + DateFormatUtil.getNowTime() + "_tmp.zip");
        try {
            multipartfile.transferTo(file);
        } catch (IOException e) {
            e.printStackTrace();
            logger.error(zipName + "上传失败");
        }
        ZipFile zipFile = null;
        try {
            zipFile = new ZipFile(file);
        } catch (IOException e) {
            e.printStackTrace();
            logger.error(zipName + "实际格式不是zip");
        }
        try {
            for (Enumeration e = zipFile.entries(); e.hasMoreElements(); ) {
                ZipEntry entry = (ZipEntry) e.nextElement();
                String filename = entry.getName();
                filename = filename.replace('\\', '/');
                String lcName = filename.toLowerCase();
                //若是文件目录或者不是wav文件循环
                if (lcName.endsWith(".wav") || lcName.endsWith(".pcm")) {
                    InputStream in = zipFile.getInputStream(entry);
                    File f = new File(descDir + StringUtil.FILESEPARATOR + filename);
                    if (!f.getParentFile().exists()) {
                        f.getParentFile().mkdir();
                    }
                    if (!f.exists()) f.createNewFile();
                    OutputStream out = new FileOutputStream(f);
                    byte[] buf1 = new byte[1024];
                    int len;
                    while ((len = in.read(buf1)) > 0) {
                        out.write(buf1, 0, len);
                    }
                    in.close();
                    out.close();
                    fileNameList.add(filename);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            logger.error(zipName + "解压失败");
        } finally {
            try {
                zipFile.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                file.delete();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return fileNameList;
    }

    private static int byteChangeToInt(byte byte1, byte byte2, byte byte3, byte byte4) {
        int value1 = ((int) byte1 & 0xff) << 24;
        int value2 = ((int) byte2 & 0xff) << 16;
        int value3 = ((int) byte3 & 0xff) << 8;
        int value4 = (int) byte4 & 0xff;
        return value1 | value2 | value3 | value4;
    }


    private static int byteChangeToInt(byte[] bytes) {

        int t1 = (bytes[3] & 0xff) << 24;
        int t2 = (bytes[2] & 0xff) << 16;
        int t3 = (bytes[1] & 0xff) << 8;
        int t4 = bytes[0] & 0xff;
        //logger.info(b[1]&0xff);//输出的是一个整形数据
        //在java中，设计int和比int位数来的小的类型b，如byte,char等，都是先把小类型扩展成int再来运算，
        //return( t1<<24)+(t2<<16)+(t3<<8)+t4;//必须加括号
        return t1 + t2 + t3 + t4;

    }

    //int 转byte
    private static byte[] intTobyte(int a, int len) {
        byte[] t = new byte[len];
        t[0] = (byte) ((a & 0xff));
        if (len > 1)
            t[1] = (byte) ((a & 0xff00) >> 8);
        if (len > 2)
            t[2] = (byte) ((a & 0xff0000) >> 16);
        if (len > 3)
            t[3] = (byte) ((a & 0xff000000) >> 24);
        return t;
    }

    /**
     * 把path文件/文件夹压缩为zipPath文件（包括路径）
     *
     * @param zipPath
     * @param path
     * @return
     */
    public static boolean zipFiles(String zipPath, String path) {
        try {
            File f = new File(path);
            if (f.exists()) {
                String f_path = f.getCanonicalPath();
                String f_name = f.getName();
                int pre_l = f_path.length() - f_name.length();
                List<File> pathList = new ArrayList<File>();
                ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipPath));
                out.setEncoding(FILE_ENCODING);
                byte[] buf = new byte[1024];
                int len;
                if (f.isDirectory()) {
                    pathList.add(f);
                } else {
                    out.putNextEntry(new org.apache.tools.zip.ZipEntry(f_name + StringUtil.FILESEPARATOR + f.getName()));
                    FileInputStream in = new FileInputStream(f);
                    while ((len = in.read(buf)) > 0) {
                        out.write(buf, 0, len);
                    }
                    in.close();
                    out.closeEntry();
                    out.flush();
                }
                while (pathList.size() > 0) {
                    File file_ = pathList.remove(0);
                    File[] f_s = file_.listFiles();
                    for (File f_ : f_s) {
                        if (f_.isDirectory()) {
                            pathList.add(f_);
                        } else {
                            out.putNextEntry(new org.apache.tools.zip.ZipEntry(
                                    f_.getCanonicalPath().substring(pre_l)));
                            FileInputStream in = new FileInputStream(f_);
                            while ((len = in.read(buf)) > 0) {
                                out.write(buf, 0, len);
                            }
                            in.close();
                        }
                    }
                }
                out.close();
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 获取语音文件总时长(单位秒)
     *
     * @param f
     * @return
     * @throws Exception
     */
    public static double calcWavDur(File f) {
        double wavMS = 0.0;
        AudioInputStream ais = null;
        try {
            FileInputStream fis = new FileInputStream(f);
            BufferedInputStream bis = new BufferedInputStream(fis);
            ais = AudioSystem.getAudioInputStream(bis);
            wavMS = calcWavDur(ais);
            ais.close();
            bis.close();
            fis.close();
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("音频格式错误");
        }
        return wavMS;
    }

    private static double calcWavDur(AudioInputStream ais) {
        AudioFormat af = ais.getFormat();
        float frameRate = af.getFrameRate();
        long frameLength = ais.getFrameLength();
        double dur = frameLength / frameRate;
        try {
            ais.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return dur;
    }


    private static FTPClient getFtpClient(String host, int port, String username, String password) {
        FTPClient ftpClient = new FTPClient();
        try {
            //连接ftp
            ftpClient.connect(host, port);
            ftpClient.login(username, password);
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            int reply = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftpClient.disconnect();
                return null;
            }
        } catch (SocketException e) {
            logger.info("【FTP】 " + host + "连接失败");
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ftpClient;
    }


    public static void main(String[] args) {
//        copyFeil("C:\\Users\\hccl\\Desktop\\spsMessage\\spsMessage", "tel_0094_01.wav", "C:\\Users\\hccl\\Desktop\\spsMessage\\spsMessage\\newPath");

//        File file = new File("C:\\Users\\hccl\\Desktop\\spsMessage\\spsMessage\\tel_0163_01.wav");
//        boolean b = verifyIsALAW_OR_PCM(file);

        File file = new File("D:\\root\\stt\\0001.bmp");
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
            byte[] bytes = new byte[54];
            fis.read(bytes);
            int width = byteChangeToInt(bytes[21], bytes[20], bytes[19], bytes[18]);
            int height = byteChangeToInt(bytes[25], bytes[24], bytes[23], bytes[22]);
            System.out.println(width + "  " + height);


            FileInputStream fis2 = new FileInputStream(file);
            BufferedInputStream bis = new BufferedInputStream(fis2);
            byte[] wb = new byte[4];//读取宽度的字节数组
            byte[] hb = new byte[4];//读取高度的字节数组
            byte[] temp1 = new byte[18];
            bis.read(temp1);//bis.skip(18);//跳过前18个byte
            bis.read(wb);//读取宽度
            bis.read(hb);//读取高度
            width = byteChangeToInt(wb);
            height = byteChangeToInt(hb);
            System.out.println(width + "<>" + height);


        } catch (Exception e) {
            e.printStackTrace();
        }


    }

}
